<template>
  <div class="Icon" :style="lock === false ? { height: '52px' } : { height: '452px' }">
    <div class="icon_top">
      <div class="uprame">
        <span @click="() => {
          lock = !lock; $emit('showBottomSheet', lock);
          nextTick(() => {
            jargonNode && jargonNode.click()
          })
        }">
          <CircleUP ref="upNode" v-if="lock" />
          <CircleDown v-else />
        </span>
      </div>
      <!-- 输入框 -->
      <!-- @focus="lock = false" 这里是输入框聚焦的事件   @blur当用户失去焦点事件 -->
      <div id="contentTable" ref="editor" :class="['empty:after:content-[attr(placeholder)]', 'shuru', {
        'empty:after:text-gray-400': !disabled,
        'empty:after:text-gray-300': disabled,
      }]" contenteditable suppressContentEditableWarning @keydown="event.handleKeydown" />
      <!--  @input="() => event.handleInput"  -->

      <!-- 点击图标 展示emoji图片列表 -->
      <EmojiSticker @click="() => {
        lock = !lock; $emit('showBottomSheet', lock);
        nextTick(() => {
          emojiNode && emojiNode.click()
        })
      }" />

      <button :disabled="disabled" class="button" @click="event.send()">
        发送
      </button>
    </div>
    <!-- 弹出层 -->
    <div class="popup" v-show="lock">
      <div class="buttonList">

        <button v-show="data.toolbar[0].value == 'emoji'" :title="data.toolbar[0].title" ref="emojiNode"
          class="emoji p-1 rounded-md hover:bg-gray-200 text-gray-500" @click="data.toolbar[0].onClick"
          @blur="data.toolbar[0].onBlur">
          <span class="text-[30px] flex items-center justify-center">
            <component v-if="data.toolbar[0].icon && typeof data.toolbar[0].icon != 'string'"
              :is="data.toolbar[0].icon" />
            <img v-else :src="data.toolbar[0].icon" :alt="data.toolbar[0].title" class="w-auto h-[1em]" />
          </span>
        </button>

        <!-- jargon -->
        <button v-show="data.toolbar[1].value == 'jargon'" :title="data.toolbar[1].title" ref="jargonNode"
          class="jargon p-1 rounded-md hover:bg-gray-200 text-gray-500" @click="data.toolbar[1].onClick"
          @blur="data.toolbar[1].onBlur">
          <span class="text-[30px] flex items-center justify-center">
            <component v-if="data.toolbar[1].icon && typeof data.toolbar[1].icon != 'string'"
              :is="data.toolbar[1].icon" />
            <img v-else :src="data.toolbar[1].icon" :alt="data.toolbar[1].title" class="w-auto h-[1em]" />
          </span>
        </button>

        <button v-show="data.toolbar[2].value == 'userComment'" :title="data.toolbar[2].title" ref="userComment"
          class="jargon p-1 rounded-md hover:bg-gray-200 text-gray-500" @click="data.toolbar[2].onClick"
          @blur="data.toolbar[2].onBlur">
          <span class="text-[30px] flex items-center justify-center">
            <component v-if="data.toolbar[2].icon && typeof data.toolbar[2].icon != 'string'"
              :is="data.toolbar[2].icon" />
            <img v-else :src="data.toolbar[2].icon" :alt="data.toolbar[2].title" class="w-auto h-[1em]" />
          </span>
        </button>

      </div>

      <div class="showClass" ref="modal">

      </div>
    </div>

    <!-- 点击任意位置都可以收回弹出层 -->
    <div v-if="lock" class="z-40 fixed inset-0 m-auto" @click="lock = false"></div>
  </div>
  <!-- 取消在iphone端的点击输入框页面变大效果 -->
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="viewport"
    content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
</template>

<script setup lang="ts">
import './style.css'
import EmojiIcon from '@/components/icon/Emotion.vue';
import JargonIcon from '../icon/Jaygon.vue';
import CardIcon from '../icon/Car.vue';
import { type IProps } from './props';
import { type IEmits } from './emits';
import { createElementBlock, nextTick, onMounted, onUpdated, reactive, ref, shallowRef, watch } from 'vue';
import { Confirm } from '../modal';
import { emojiToText, htmlToText, textToEmoji } from '@/utils/render';
import { EMOJI } from '../icon';
import CircleUP from '../icon/CircleUP.vue';
import CircleDown from '../icon/CircleDown.vue';
import EmojiSticker from '@/components/icon/EmojiSticker.vue';
import UserComment from '../icon/UserComment.vue';
import Scrollbar from '../scrollbar/Scrollbar.vue';


// withDefaults是为了给获取到父元素穿过来的值 给默认值 ，这里给的是泛型的接口
const props = withDefaults(defineProps<IProps>(), {
  placeholder: '按Enter发送',
  disabled: false,
});

const lock = ref(false);

const emits = defineEmits<IEmits>();

const jargonNode = ref<HTMLElement>()
const emojiNode = ref<HTMLElement>()
const upNode = ref<SVGAElement>()

const messageText = ref()

const model = defineModel({ type: String });
// 这里调用的是输入事件
const editor = ref<HTMLDivElement>();
const modal = ref<HTMLDivElement>();
const scrollbar = ref();

const data = reactive({
  toolbar: [
    {
      ref: 'emojiNode',
      value: 'emoji',
      // 浅层的响应式引用
      icon: shallowRef(EmojiIcon),
      title: '表情',
      // 点击方法的参数是鼠标事件
      onClick: (e: MouseEvent) => {
        if (data.currentToolBar !== 'emoji') {
          data.showModal = false;
          data.showModal = true;
        } else {
          data.showModal = !data.showModal;
        }
        data.currentToolBar = 'emoji';

        if (modal.value) {
          modal.value.innerHTML = '';
        }
        // 创建表情弹窗
        modal.value?.setAttribute(
          'class',
          `${data.modalClass} grid h-[335px] grid-cols-8 gap-2 relative`
        );
        const fragment = new DocumentFragment();

        data.emoji.forEach(img => {
          fragment.appendChild(img);
        });
        modal.value?.appendChild(fragment);
      },
      // 失去焦点时
      onBlur: () => {
        if (data.currentToolBar !== 'emoji') {
          data.showModal = false;
        }
      },
    },
    {
      ref: 'jargonNode',
      value: 'jargon',
      icon: shallowRef(JargonIcon),
      title: '话术',
      onClick: (e: MouseEvent) => {
        // 当前点击的工具栏为话术时
        if (data.currentToolBar !== 'jargon') {
          data.showModal = false;
          data.showModal = true;
        } else {
          data.showModal = !data.showModal;
        }
        data.currentToolBar = 'jargon';
        if (modal.value) {
          // 这是那个弹出框DOm
          modal.value.innerHTML = '';
        }
        const el = e.currentTarget as HTMLDivElement;
        const rect = el.getBoundingClientRect();

        modal.value?.setAttribute(
          'class',
          `${data.modalClass} h-[335px] relative flex flex-col-reverse gap-1`
        );
        data.modalPosition.top = rect.top - 280 - 16;
        data.modalPosition.left = rect.left;

        const fragment = new DocumentFragment();

        data.jargon.forEach(sapn => {
          fragment.appendChild(sapn);
        });
        modal.value?.appendChild(fragment);
      },
      // 失去焦点时
      onBlur: () => {
        if (data.currentToolBar !== 'jargon') {
          data.showModal = false;
        }
      },
    },
    {
      value: 'userComment',
      icon: shallowRef(UserComment),
      title: '用户评论',
      onClick: (e: MouseEvent) => {
        if (data.currentToolBar !== 'userComment') {
          data.showModal = false;
          data.showModal = true;
        } else {
          data.showModal = !data.showModal;
        }
        data.currentToolBar = 'userComment';

        if (modal.value) {
          modal.value.innerHTML = '';
        }
        // 鼠标事件当时正在处理该事件的元素 的类型是 HTMLDivElement 具体的DOM
        const el = e.currentTarget as HTMLDivElement;

        // 返回元素的大小及其相对于视口的位置 将值赋rect
        const rect = el.getBoundingClientRect();

        // 创建表情弹窗
        modal.value?.setAttribute(
          'class',
          `${data.modalClass}  h-[335px]  relative`
        );
        data.modalPosition.top = rect.top - 280 - 16;
        data.modalPosition.left = rect.left;
        // DocumentFragment用于在编译模板时临时存放和处理元素
        const fragment = new DocumentFragment();

        data.userComment.forEach(UserComment => {
          fragment.appendChild(UserComment);
        });

        modal.value?.appendChild(fragment);
      },
      // 失去焦点时
      onBlur: () => {
        if (data.currentToolBar !== 'userComment') {
          data.showModal = false;
        }
      },
    },
    {
      value: 'card',
      icon: shallowRef(CardIcon),
      title: '卡片',
      onClick: async (_: MouseEvent) => {
        // 如果editor存在
        if (editor.value) {
          // 这里的Confirm确认框的方法
          const ok = await Confirm({
            // 内容:
            message: '确定发送卡片吗？',
          });
          if (ok) {
            emits('enter', '【卡片消息】');
          }
        }
      },
    },
  ],
  /**
   * 拟态类
   */
  modalClass:
    'modal z-50 p-2 bg-white h-[280px] overflow-x-hidden overflow-y-auto',
  /**
   * 显示模式
   */
  showModal: false,
  /**
   * 当前工具栏 */
  currentToolBar: '',
  // 类型是对象，有两个键值对，其一键名是top，其二键名是left，其值都为0
  // 模拟位置
  modalPosition: {
    top: 0,
    left: 0,
  },
  // 键名是emoji，类型是一个数组，数组里面是HTMLImageElement的类型，就是这个数组只能包含图片元素
  emoji: <HTMLImageElement[]>[],
  // 键名是jargon，类型是一个数组，数组里面包括着HTMLDiveElement类型 ，就是html<div>中的DOM元素的数组类型
  jargon: <HTMLDivElement[]>[],
  // 用户评论
  userComment: <HTMLDivElement[]>[],
});

const event = {
  // handleInput方法参数的类型是输入事件
  handleInput(e: InputEvent) {
    // e是一个事件对象,它代表了一个输入事件,当用户输入元素如<input>,<div>交互时,会触发输入事件
    const el = e.target as HTMLElement;
    // 获取触发事件的元素，调用trim()方法用于移除字符串两端的空白字符
    const message = el.innerHTML.trim();
    // htmlToText()将转换后的消息从HTML格式转换为纯文本格式
    // emojiToText将消息中的emoji转换为文本
    model.value = htmlToText(emojiToText(message));
    if (scrollbar.value) {
      scrollbar.value.scrollToBottom()
    }
  },
  // 按下 键盘事件
  handleKeydown(e: KeyboardEvent) {
    // el是触发事件的DOM元素
    const el = e.target as HTMLElement;
    if (e.key === 'Enter') {
      // 取消浏览器的默认事件
      e.preventDefault();
      // el.innerHTML用于设置或获取el元素内部HTML内容 trim()用于删除前后空白符和行结束符
      const message = el.innerHTML.trim();
      if (message) {
        emits('enter', htmlToText(emojiToText(message)));

        model.value = '';
        el.innerHTML = '';
      }
      return;
    }
    if (e.key === 'Tab') {
      e.preventDefault();
      this.insert('\t');
      return;
    }
  },
  send() {
    if (model.value) {
      console.log(emojiToText(model.value));
      emits('enter', htmlToText(emojiToText(model.value)));
      model.value = '';
      this.reset();
    }
  },
  reset() {
    nextTick(() => {
      if (editor.value) {
        editor.value.innerHTML = '';
      }
    });
  },
  insert(content: string) {
    // window.getSelection()返回一个Selection对象，该对象包含当前在文档中被用户或脚本选定的文本范围
    const selection = window.getSelection() as Selection;
    // 返回选区中'Range'对象的数量
    if (selection.rangeCount > 0) {
      // 返回选区中指定索引的'Range'对象
      const range = selection.getRangeAt(0);
      // createTextNode是一个DOM方法，
      const tabNode = document.createTextNode(content);
      // 在范围内容之前插入节点
      range.insertNode(tabNode);
      range.setStartAfter(tabNode);
      range.setEndAfter(tabNode);
      selection.removeAllRanges();
      selection.addRange(range);
    }
    if (scrollbar.value) {
      scrollbar.value.scrollToBottom();
    }
  },
  append(content: string) {
    nextTick(() => {
      if (editor.value) {
        editor.value.innerHTML += content;
        // data.showModal = false;
      }
    });
  },
};

nextTick(() => {
  const insertAtCursor = (text: any) => {
    const shuru: any = document.querySelector('.shuru')
    // 获取光标的左边界
    const startPos = shuru!.selectionStart
    // 获取光标的右边界
    const endPos = shuru!.selectionEnd
    const beforeText = messageText.value.substring(0, startPos)
    const afterText = messageText.value.substring(endPos, messageText.value.length)
    messageText.value = beforeText + text + afterText
  }
  const emojiNames = Object.keys(EMOJI);
  // 把图片都push到data.emoji数组中
  emojiNames.forEach((name: keyof typeof EMOJI) => {
    const img = document.createElement('img');

    img.src = EMOJI[name];
    img.style.width = '34px';
    img.style.height = '34px';
    img.setAttribute(
      'class',
      'cursor-pointer hover:bg-gray-100 p-2 rounded'
    );
    // 当鼠标点击img DOM 事件
    img.addEventListener('click', () => {
      // 添加子节点到父元素的末尾
      event.append(textToEmoji(name))
    });
    // 添加数组img中的一个或多个元素
    data.emoji.push(img)
  });

  // 粘贴事件监听
  if (editor.value) {
    editor.value?.addEventListener('paste', function (e) {
      // 阻止默认的粘贴行为
      e.preventDefault();

      // 获取剪贴板数据
      // @ts-ignore
      var clipboardData = e.clipboardData || window.clipboardData;
      var pastedText = clipboardData.getData('text/plain');

      // 创建一个新的文本节点并插入到光标位置
      var range = window.getSelection()?.getRangeAt(0);
      var textNode = document.createTextNode(htmlToText(pastedText));
      range?.deleteContents();
      range?.insertNode(textNode);

      range?.setStartAfter(textNode);
      range?.setEndAfter(textNode);
      window.getSelection()?.removeAllRanges();
      window.getSelection()?.addRange(range!);
    });
  }
  // 监听输入框发生变化
  if (editor.value) {
    const observer = new MutationObserver(mutations => {
      mutations.forEach(mutation => {
        // const el = mutation.target as HTMLElement;
        model.value = htmlToText(
          emojiToText(editor.value?.innerHTML || '')
        );
      });
    });
    observer.observe(editor.value, {
      childList: true,
      subtree: true,
      characterData: true,
    });
  }
});

watch(() => props.userComment, () => {
  // if (props.userComment) {
  //   for (const list in props.userComment) {

  //   }
  // }
  // console.log(props.userComment);
  let ed = 0
  const contentComment = document.createElement('div')
  contentComment.className = 'flex flex-col gap-2 box-content'
  for (const ls of props.userComment as Record<string, any>[]) {
    ed++
    const comment = document.createElement('div')
    comment.className = 'comment flex flex-col border-dashed border-2 border-orange-500'
    const ballNum = document.createElement('span')
    ballNum.innerText = `${ed}`
    comment.innerText = '用户评论信息：' + `${ed}`

    const comment_create_time = document.createElement('span')
    comment_create_time.className = 'text-[#4B5563]'
    comment_create_time.innerText = ls['comment_create_time']
    const blogger_nickname = document.createElement('span')
    const blogger_ip = document.createElement('span')
    blogger_nickname.innerText = '博主：' + ls['blogger_nickname']
    blogger_ip.innerText = ` [${ls['ranking']['ip_location']}]`
    blogger_ip.className = 'text-rose-500'
    blogger_nickname.appendChild(blogger_ip)
    comment.appendChild(comment_create_time)
    comment.appendChild(blogger_nickname)

    const text = document.createElement('span')
    text.innerText = '评论内容：'
    const textSpan = document.createElement('span')
    textSpan.innerText = ls['text']
    textSpan.className = 'bg-orange-400 text-white rounded-xl px-3'

    const blogger_ranking = document.createElement('span')
    blogger_ranking.innerText = '博主排名：' + ls['ranking']['ranking']

    const blogger_total = document.createElement('span')
    blogger_total.innerText = '博主线索：' + ls['ranking']['total']
    text.appendChild(textSpan)

    comment.appendChild(text)
    comment.appendChild(blogger_ranking)
    comment.appendChild(blogger_total)

    contentComment.appendChild(comment)
  }

  data.userComment.push(contentComment)

  if (props.userComment?.length == 0) {
    const nulltitle = document.createElement('div')
    nulltitle.innerText = '该用户暂无评论'
    nulltitle.className = 'flex text-[20px]'

    data.userComment.push(nulltitle)
  }

})

watch(
  () => props.jargon,
  () => {
    if (
      props.jargon &&
      Object.keys(props.jargon).length > 0 &&
      data.jargon.length === 0
    ) {
      const tabs = document.createElement('div');
      tabs.setAttribute(
        'class',
        'flex flex-row gap-1 border-t border-gray-200 p-1'
      );
      const content = document.createElement('div');
      content.setAttribute(
        'class',
        'flex-1 flex flex-col items-start gap-2'
      );

      const keys = Object.keys(props.jargon);
      let current = '';
      keys.forEach((key, index) => {
        const button = document.createElement('button');
        button.innerHTML = key;
        const btnClass = 'px-2 py-1 rounded hover:bg-orange-100';
        button.setAttribute('class', btnClass);
        button.addEventListener('click', () => {
          // 如果点击的是同一个的话 就返回当前的 不做其他操作
          if (current === key) {
            return;
          }

          // 重复一遍当前的点击是谁
          current = key;

          // 移除其他按钮样式
          const btns = tabs.childNodes;
          btns.forEach(btn => {
            if (btn.nodeType === 1) {
              (btn as HTMLButtonElement).setAttribute(
                'class',
                btnClass
              );
            }
          });

          // 当前按钮样式
          button.setAttribute(
            'class',
            `${btnClass} bg-orange-100`
          );

          content.innerHTML = '';

          props.jargon![key].forEach(text => {
            const span = document.createElement('span');
            span.innerHTML = text;
            span.setAttribute(
              'class',
              'cursor-pointer hover:bg-gray-100 p-2 rounded bg-gray-50'
            );
            span.addEventListener('click', () => {
              event.append(text);
            });
            content.appendChild(span);
          });
        });
        if (index === 0) {
          button.click();
        }
        tabs.appendChild(button);
      });
      data.jargon.push(tabs, content);
    }
  },
  { deep: true }
);

defineExpose({
  reset: event.reset,
});

</script>